package pr.lanmu.create;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import lombok.SneakyThrows;
import pr.lanmu.controller.ModuleController;
import pr.lanmu.service.ModuleService;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;

/**
 * 给controller生成req和res
 */
@SuppressWarnings("all")
public class CreateReqAndRes {
    private static final String path = System.getProperty("user.dir") + "/src/main/java/";

    public static void main(String[] args) throws IOException {
        Class<?> controller = ModuleController.class;
        Class<?> service = ModuleService.class;
//        List<String> methodNames = List.of("post", "delete", "put");
//        List<String> methodDoc = List.of("新增定时任务", "删除定时任务", "修改定时任务");
//        List<String> methodUrl = List.of("/post", "/delete", "/put");
        List<String> methodNames = List.of("getModuleTableAndPermissionRules");
        List<String> methodDoc = List.of("查询模块绑定的表和关联的接口及接口的校验规则");
        List<String> methodUrl = List.of("getModuleTableAndPermissionRules");
        createHandler(controller,
                methodNames,
                methodDoc,
                methodUrl);
        createService(service,
                methodNames,
                methodDoc,
                methodUrl);
        createReq(controller,
                methodNames);
        createRes(controller,
                methodNames);
    }

    @SneakyThrows
    private static void createService(Class<?> clazz, List<String> methodNames, List<String> methodDoc, List<String> methodUrl) {
        //给service的java文件中添加方法
        String name = clazz.getSimpleName();
        String handlePath = path + clazz.getPackage()
                .getName()
                .replace(".",
                        "/") + "/" + name + ".java";
        String service = name.substring(0,
                name.indexOf("Service"));
        BufferedReader br = new BufferedReader(new FileReader(Paths.get(handlePath)
                .toFile()));
        StringBuilder body = new StringBuilder();
        String line;
        while ((line = br.readLine()) != null) {
            body.append(line)
                    .append("\n");
        }
        IoUtil.close(br);
        body = new StringBuilder(body.substring(0,
                body.lastIndexOf("}")));
        PrintWriter pw = new PrintWriter(Files.newOutputStream(Paths.get(handlePath)));
        pw.println(body + "\n");
        for (int i = 0; i < methodNames.size(); i++) {
            pw.println(String.format("""
                        /**
                         * %s
                         *
                         * @param param .
                         * @return .
                         */
                        public Res<%s> %s(%s param) {
                            return Res.success(() -> null);
                        }
                    """, methodDoc.get(i), service + "Res." + methodNames.get(i), methodNames.get(i), service + "Req." + methodNames.get(i)));
        }
        pw.println("}");
        IoUtil.close(pw);
    }

    @SneakyThrows
    private static void createHandler(Class<?> clazz, List<String> methodNames, List<String> methodDoc, List<String> methodUrl) {
        //给controller的java文件中添加方法
        String name = clazz.getSimpleName();
        String handlePath = path + clazz.getPackage()
                .getName()
                .replace(".",
                        "/") + "/" + name + ".java";
        String controller = name.substring(0,
                name.indexOf("Controller"));
        BufferedReader br = new BufferedReader(new FileReader(Paths.get(handlePath)
                .toFile()));
        StringBuilder body = new StringBuilder();
        String line;
        while ((line = br.readLine()) != null) {
            body.append(line)
                    .append("\n");
        }
        IoUtil.close(br);
        body = new StringBuilder(body.substring(0,
                body.lastIndexOf("}")));
        PrintWriter pw = new PrintWriter(Files.newOutputStream(Paths.get(handlePath)));
        pw.println(body + "\n");
        for (int i = 0; i < methodNames.size(); i++) {
            pw.println(String.format("\t@Operation(summary=\"%s\")",
                    methodDoc.get(i)));
            pw.println(String.format("\t@PostMapping(\"%s\")",
                    methodUrl.get(i)));
            pw.println(String.format("\tpublic Res<%s> %s(@RequestBody @Validated %s param) {",
                    controller + "Res." + methodNames.get(i),
                    methodNames.get(i),
                    controller + "Req." + methodNames.get(i)));
            pw.println(String.format("\t\treturn service.%s(param);",
                    methodNames.get(i)));
            pw.println("\t}\n");
        }
        pw.println("}");
        IoUtil.close(pw);
    }

    private static void createReq(Class clazz, List<String> methodNames) throws IOException {
        String reqPath = path + clazz.getPackage()
                .getName()
                .replace(".",
                        "/") + "/request/";
        FileUtil.mkdir(reqPath);
        String name = clazz.getSimpleName();
        String controller = name.substring(0,
                name.indexOf("Controller"));
        String req = reqPath + controller + "Req.java";
        boolean exist = FileUtil.exist(req);
        if (exist) {
            BufferedReader br = new BufferedReader(new FileReader(Paths.get(req)
                    .toFile()));
            StringBuilder body = new StringBuilder();
            String line;
            while ((line = br.readLine()) != null) {
                body.append(line)
                        .append("\n");
            }
            IoUtil.close(br);
            body = new StringBuilder(body.substring(0,
                    body.lastIndexOf("}")));
            PrintWriter pw = new PrintWriter(Files.newOutputStream(Paths.get(req)));
            pw.println(body);
            for (String methodName : methodNames) {
                pw.println("\t@Data");
                pw.println("\t@EqualsAndHashCode(callSuper = false)");
                pw.println(String.format("\t@Schema(name = \"%sReq-%s\")",
                        controller,
                        methodName));
                pw.println(String.format("\tpublic static class %s {",
                        methodName));
                pw.println("\t}");
            }
            pw.println("}");
            IoUtil.close(pw);
        } else {
            PrintWriter pw = new PrintWriter(Files.newOutputStream(Paths.get(req)));
            pw.println(String.format("package %s.request;\n",
                    clazz.getPackage()
                            .getName()));
            pw.println("import io.swagger.annotations.ApiModel;");
            pw.println("import io.swagger.annotations.ApiModelProperty;");
            pw.println("import lombok.Data;");
            pw.println("import lombok.EqualsAndHashCode;");
            pw.println("import lombok.experimental.Accessors;\n");
            pw.println(String.format("public class %sReq {",
                    controller));
            for (String methodName : methodNames) {
                pw.println("\t@Data");
                pw.println("\t@Accessors(chain = true)");
                pw.println("\t@EqualsAndHashCode(callSuper = false)");
                pw.println(String.format("\t@Schema(name = \"%sReq-%s\")",
                        controller,
                        methodName));
                pw.println(String.format("\tpublic static class %s {",
                        methodName));
                pw.println("\t}");

            }
            pw.println("}");
            IoUtil.close(pw);
        }
    }

    private static void createRes(Class clazz, List<String> methodNames) throws IOException {
        String resPath = path + clazz.getPackage()
                .getName()
                .replace(".",
                        "/") + "/response/";
        FileUtil.mkdir(resPath);
        String name = clazz.getSimpleName();
        String controller = name.substring(0,
                name.indexOf("Controller"));
        String res = resPath + controller + "Res.java";
        boolean exist = FileUtil.exist(res);
        if (exist) {
            BufferedReader br = new BufferedReader(new FileReader(Paths.get(res)
                    .toFile()));
            StringBuilder body = new StringBuilder();
            String line;
            while ((line = br.readLine()) != null) {
                body.append(line)
                        .append("\n");
            }
            IoUtil.close(br);
            body = new StringBuilder(body.substring(0,
                    body.lastIndexOf("}")));
            PrintWriter pw = new PrintWriter(Files.newOutputStream(Paths.get(res)));
            pw.println(body);
            for (String methodName : methodNames) {
                pw.println("\t@Data");
                pw.println("\t@Accessors(chain = true)");
                pw.println("\t@EqualsAndHashCode(callSuper = false)");
                pw.println(String.format("\t@Schema(name = \"%sRes-%s\")",
                        controller,
                        methodName));
                pw.println(String.format("\tpublic static class %s {",
                        methodName));
                pw.println("\t}");
            }
            pw.println("}");
            IoUtil.close(pw);
        } else {
            PrintWriter pw = new PrintWriter(Files.newOutputStream(Paths.get(res)));
            pw.println(String.format("package %s.response;\n",
                    clazz.getPackage()
                            .getName()));
            pw.println("import io.swagger.annotations.ApiModel;");
            pw.println("import io.swagger.annotations.ApiModelProperty;");
            pw.println("import lombok.Data;");
            pw.println("import lombok.EqualsAndHashCode;");
            pw.println("import lombok.experimental.Accessors;\n");
            pw.println(String.format("public class %sRes {",
                    controller));
            for (String methodName : methodNames) {
                pw.println("\t@Data");
                pw.println("\t@EqualsAndHashCode(callSuper = false)");
                pw.println(String.format("\t@Schema(name = \"%sRes-%s\")",
                        controller,
                        methodName));
                pw.println(String.format("\tpublic static class %s {",
                        methodName));
                pw.println("\t}");
            }
            pw.println("}");
            IoUtil.close(pw);
        }
    }
}